/*
 * AuthUserFile.cpp
 *
 *  Created on: 2017年10月27日
 *      Author: terry
 */

#include "AuthUserFile.h"
#include <fstream>
#include "TStringUtil.h"
#include "TStlUtil.h"
#include "Md5Digest.h"

namespace util
{

const char* AuthUserFile::REALM = "HttpServer";

AuthUserFile::AuthUserFile()
{
}

AuthUserFile::~AuthUserFile()
{
}

bool AuthUserFile::load(const char* filepath)
{
	std::ifstream ifs;
	ifs.open(filepath);
	if (!ifs.is_open())
	{
		return false;
	}

	std::string line;
	while (ifs.good())
	{
		std::getline(ifs, line);
		if (line.empty())
		{
			continue;
		}

		std::vector<std::string> parts;
		comn::StringUtil::split(line, ':', parts);
		if (parts.size() == 3)
		{
			AuthUser authUser;
			authUser.username = parts[0];
			authUser.realm = parts[1];
			authUser.password = parts[2];

			m_users.push_back(authUser);
		}
	}

	ifs.close();
	return true;
}

bool AuthUserFile::check(const std::string& username, const std::string& password)
{
	AuthUser authUser;
	if (!find(username, authUser))
	{
		return false;
	}

	if (authUser.password == password)
	{
		return true;
	}

	std::string content(username);
	content += ":";
	content += authUser.realm;
	content += ":";
	content += password;
	std::string computed = Md5Digest::make(content);

	return (computed == authUser.password);
}

bool AuthUserFile::check(const std::string& username, const std::string& password, const std::string& realm)
{
	AuthUser authUser;
	if (!find(username, authUser))
	{
		return false;
	}

	if (authUser.password == password && authUser.realm == realm)
	{
		return true;
	}

	std::string content(username);
	content += ':';
	content += authUser.realm;
	content += password;
	std::string computed = Md5Digest::make(content);

	return (computed == password);
}

size_t AuthUserFile::size() const
{
	return m_users.size();
}

AuthUserFile::AuthUser AuthUserFile::get(size_t idx) const
{
	if (idx < 0 || idx >= m_users.size())
	{
		return AuthUserFile::AuthUser();
	}
	return m_users[idx];
}

AuthUserFile::AuthUser& AuthUserFile::get(size_t idx)
{
	return m_users[idx];
}

bool AuthUserFile::find(const std::string& username, AuthUser& authUser)
{
	size_t idx = find(username);
	if (idx == (size_t )-1)
	{
		return false;
	}

	authUser = m_users[idx];
	return true;
}

size_t AuthUserFile::find(const std::string& username)
{
	for (size_t i = 0; i < m_users.size(); ++i)
	{
		if (username == m_users[i].username)
		{
			return i;
		}
	}
	return -1;
}

bool AuthUserFile::exist(const std::string& username)
{
	AuthUser authUser;
	return AuthUserFile::find(username, authUser);
}

void AuthUserFile::clear()
{
	m_users.clear();
}

bool AuthUserFile::remove(const std::string& username)
{
	size_t idx = find(username);
	if (idx == (size_t)-1)
	{
		return false;
	}

	comn::StlUtil::removeAt(m_users, idx);
	return true;
}

bool AuthUserFile::add(const AuthUserFile::AuthUser& authUser)
{
	if (authUser.username.empty())
	{
		return false;
	}

	m_users.push_back(authUser);
	return true;
}

bool AuthUserFile::add(const std::string& username, const std::string& password, const std::string& realm)
{
	AuthUserFile::AuthUser authUser;
	authUser.username = username;
	authUser.password = password;
	authUser.realm = realm;
	return add(authUser);
}

std::string AuthUserFile::getRealm()
{
	for (size_t i = 0; i < m_users.size(); ++i)
	{
		if (m_users[i].realm.size() > 0)
		{
			return m_users[i].realm;
		}
	}
	return REALM;
}

} /* namespace util */
